import { _decorator, Component, Node, Vec3, ParticleSystemComponent, ColliderComponent, RigidBodyComponent, ICollisionEvent, EventInfo } from "cc";
import { RoadPoint } from "./RoadPoint";
import { Constants } from "../data/Constants";
import { CustomerEventListener } from "../data/CustomerEventListener";
import { AudioManager } from "./AudioManager";
import { RunTimeData } from "../data/RunTimeData";
const { ccclass, property } = _decorator;

const tempVec = new Vec3();
const EventName = Constants.EventName;

@ccclass("Car")
export class Car extends Component {

    @property({ tooltip: '加速度' })
    acceleration: number = 0.2
    @property({ tooltip: '最大速度' })
    maxSpeed: number = 0.5;
    @property({ tooltip: '最小速度' })
    minSpeed: number = 0.2;

    private currRoadPoint: RoadPoint = null;
    private pointA: Vec3 = new Vec3();
    private pointB: Vec3 = new Vec3();
    private currSpeed: number = 0.3;
    private isMoving: boolean = false;
    private offset = new Vec3();

    //
    private originRotation: number = 0;
    private targetRotation: number = 0;
    private centerPoint: Vec3 = new Vec3();
    private currRotation = 0;
    // 旋转的弧度
    private rotMeasure: number = 0;

    // 当前是否为玩家控制小车
    private isMainCar: boolean = false;
    // 小车是否在订单中
    private isInOrder: boolean = false;

    private overCD: Function = null;
    // 相机
    private camera: Node = null;
    // 尾气
    private gas: ParticleSystemComponent = null;

    start(): void {
        CustomerEventListener.on(EventName.FINISHED_WALK, this.finishedWalk, this);
    }


    update(dt: number): void {

        if (this.isInOrder) {
            return;
        }

        if (this.isMoving) {

            this.offset.set(this.node.worldPosition);

            this.currSpeed += this.acceleration * dt;
            if (this.currSpeed >= this.maxSpeed) {
                this.currSpeed = this.maxSpeed;
            }
            if (this.currSpeed <= 0.001) {
                this.isMoving = false;
            }

            switch (this.currRoadPoint.moveType) {
                // 弯道
                case RoadPoint.RoadMoveType.BEND:
                    const offsetRotation = this.targetRotation - this.originRotation;
                    let nextStation = (this.currRotation - this.originRotation) + (this.currSpeed * this.rotMeasure * (this.targetRotation > this.originRotation ? 1 : -1));
                    if (Math.abs(nextStation) > Math.abs(offsetRotation)) {
                        nextStation = offsetRotation;
                    }

                    const target = this.currRotation = nextStation + this.originRotation;
                    tempVec.set(0, target, 0);
                    this.node.eulerAngles = tempVec;
                    Vec3.rotateY(this.offset, this.pointA, this.centerPoint, nextStation * Math.PI / 180);
                    break;
                // 默认
                default:
                    const z = this.pointB.z - this.pointA.z;
                    if (z !== 0) {
                        if (z > 0) {
                            this.offset.z += this.currSpeed;
                            if (this.offset.z > this.pointB.z) {
                                this.offset.z = this.pointB.z;
                            }
                        } else {
                            this.offset.z -= this.currSpeed;
                            if (this.offset.z < this.pointB.z) {
                                this.offset.z = this.pointB.z;
                            }
                        }
                    } else {
                        const x = this.pointB.x - this.pointA.x;
                        if (x > 0) {
                            this.offset.x += this.currSpeed;
                            if (this.offset.x > this.pointB.x) {
                                this.offset.x = this.pointB.x;
                            }
                        } else {
                            this.offset.x -= this.currSpeed;
                            if (this.offset.x < this.pointB.x) {
                                this.offset.x = this.pointB.x;
                            }
                        }
                    }
                    break;
            }

            this.node.setWorldPosition(this.offset);
            Vec3.subtract(tempVec, this.pointB, this.offset);

            // 到站判断
            if (tempVec.length() <= 0.001) {
                this.arriveStation();
            }
        }
    }

    /**
     * 小车方向
     * 
     * @param entry 
     */
    public setEntry(entry: Node, isMainCar = false): void {
        this.node.setWorldPosition(entry.worldPosition);
        this.currRoadPoint = entry.getComponent(RoadPoint);
        this.isMainCar = isMainCar;
        if (!this.currRoadPoint) {
            console.warn('there is no roadPoint in: ' + entry.name);
            return;
        }

        this.pointA.set(entry.worldPosition);
        this.pointB.set(this.currRoadPoint.nextStation.worldPosition);

        const z = this.pointB.z - this.pointA.z;
        // 前后走
        if (z !== 0) {
            // 后
            if (z > 0) {
                this.node.eulerAngles = new Vec3(0, 180, 0);
            }
            // 前
            else if (z < 0) {
                this.node.eulerAngles = new Vec3(0, 0, 0);
            }
        }
        // 前后走
        else {
            const x = this.pointB.x - this.pointA.x;
            // 右
            if (x > 0) {
                this.node.eulerAngles = new Vec3(0, 270, 0);
            }
            // 左
            else if (x < 0) {
                this.node.eulerAngles = new Vec3(0, 90, 0);
            }
        }

        const collider = this.node.getComponent(ColliderComponent);
        if (this.isMainCar) {
            const gasNode = this.node.getChildByName('gas');
            this.gas = gasNode.getComponent(ParticleSystemComponent);
            this.gas.play();

            collider.on('onCollisionEnter', this.onCollisionEnter, this);
            collider.setGroup(Constants.CarGroup.MAIN_CAR);
            collider.setMask(Constants.CarGroup.OTHER_CAR);
        } else {
            collider.setGroup(Constants.CarGroup.OTHER_CAR);
            collider.setMask(-1);
        }

    }

    public setCamera(camera: Node, pos: Vec3, rotation: number): void {
        if (this.isMainCar) {
            this.camera = camera;
            this.camera.parent = this.node;
            this.camera.position = pos;
            this.camera.eulerAngles = new Vec3(rotation, 0, 0);
        }
    }

    public startRunning(): void {
        if (this.currRoadPoint) {
            this.isMoving = true;
            this.currSpeed = 0;
            this.acceleration = Math.abs(this.acceleration);
        }
    }

    public stopRunning(): void {
        // this.isMoving = false;
        this.acceleration = - Math.abs(this.acceleration);
        // 刹车事件通知
        // console.log('刹车..................')
        // CustomerEventListener.dispatchEvent(EventName.BRAKE_START, this.node);
    }

    public moveAfterFinished(cd: Function): void {
        this.overCD = cd;
    }

    public stopImmediately() {
        this.isMoving = false;
        this.currSpeed = 0;
    }

    private arriveStation(): void {
        this.currRoadPoint = this.currRoadPoint.nextStation.getComponent(RoadPoint);
        // console.log('arriveStation, currRoadPoint.type: ' + this.currRoadPoint.type);
        this.pointA.set(this.pointB);
        if (this.currRoadPoint.nextStation) {
            this.pointB.set(this.currRoadPoint.nextStation.worldPosition);

            // 玩家小车接送客
            if (this.isMoving) {
                // 接客
                if (this.currRoadPoint.type == RoadPoint.RoadPointType.GREETING) {
                    this.greetCustomer();
                }
                // 送客
                else if (this.currRoadPoint.type == RoadPoint.RoadPointType.GOODBYE) {
                    this.goodbyeCustomer();
                }
            }

            // 道路弯道，进行处理
            if (this.currRoadPoint.moveType === RoadPoint.RoadMoveType.BEND) {
                this.originRotation = this.convert(this.node.eulerAngles.y);
                // 顺时针
                if (this.currRoadPoint.clockWise) {
                    console.log('顺时针')
                    this.targetRotation = this.originRotation - 90;
                    if ((this.pointB.z < this.pointA.z && this.pointB.x > this.pointA.x) ||
                        (this.pointB.z > this.pointA.z && this.pointB.x < this.pointA.x)) {
                        this.centerPoint.set(this.pointB.x, 0, this.pointA.z);
                    } else {
                        this.centerPoint.set(this.pointA.x, 0, this.pointB.z);
                    }
                }
                // 逆时针
                else {
                    console.log('逆时针')
                    this.targetRotation = this.originRotation + 90;
                    if ((this.pointB.z > this.pointA.z && this.pointB.x > this.pointA.x) ||
                        (this.pointB.z < this.pointA.z && this.pointB.x < this.pointA.x)) {
                        console.log('逆时针-1')
                        this.centerPoint.set(this.pointB.x, 0, this.pointA.z);
                    } else {
                        console.log('逆时针-2')
                        this.centerPoint.set(this.pointA.x, 0, this.pointB.z);
                    }
                    console.log('centerPoint: ' + this.centerPoint)
                }

                // 半径计算
                Vec3.subtract(tempVec, this.pointA, this.centerPoint);
                const r = tempVec.length();
                // 弧度计算
                this.rotMeasure = 90 / (Math.PI * r / 2);
            }
        } else {
            this.isMoving = false;
            this.currRoadPoint = null;

            if (this.overCD) {
                this.overCD(this);
                this.overCD = null;

            }
        }
    }

    private greetCustomer(): void {

        const runTimeData = RunTimeData.getInstance();
        runTimeData.isOverOrder = false;

        this.isInOrder = true;
        this.currSpeed = 0;
        CustomerEventListener.dispatchEvent(EventName.GREETING, this.node.worldPosition, this.currRoadPoint.direction);

        // 关闭尾气
        this.gas.stop();

        AudioManager.playSound(Constants.AudioSource.NEW_ORDER);
    }

    /**
     * 送客: 乘客滚蛋、尾气停止、撒金币
     */
    private goodbyeCustomer(): void {

        const runTimeData = RunTimeData.getInstance();
        runTimeData.isOverOrder = true;
        this.scheduleOnce(()=>{
            runTimeData.currProcess++
        }, 1);

        this.isInOrder = true;
        this.currSpeed = 0;
        CustomerEventListener.dispatchEvent(EventName.GOODBYE, this.node.worldPosition, this.currRoadPoint.direction);

        // 关闭尾气
        console.log('gas stop');
        this.gas.stop();

        // 撒金币
        CustomerEventListener.dispatchEvent(EventName.SHOW_COIN, this.node.worldPosition);

        AudioManager.playSound(Constants.AudioSource.GET_MONEY);
    }

    private finishedWalk(): void {
        // 排放尾气
        if (this.isMainCar) {
            this.gas.play();
            this.isInOrder = false;
        }
    }

    private convert(value: number): number {
        if (value < 0) {
            value += 360;
        }
        return value;
    }

    private onCollisionEnter(event: ICollisionEvent): void {
        console.log('ICollisionEvent: ' + event);

        const collider = event.selfCollider;
        const otherCollider = event.otherCollider;

        if (collider.node.name === 'group' || otherCollider.node.name === 'group') {
            return;
        }

        collider.addMask(Constants.CarGroup.NORMAL);
        const rigidBody = this.node.getComponent(RigidBodyComponent);
        rigidBody.useGravity = true;


        const otherRigidBody = otherCollider.node.getComponent(RigidBodyComponent);
        otherRigidBody.useGravity = true;
        otherRigidBody.applyForce(new Vec3(0, 3000, -1500), new Vec3(0, 0.5, 0));

        this.gameOver();
    }

    private gameOver(): void {
        CustomerEventListener.dispatchEvent(EventName.GAME_OVER);
    }



}